﻿using System;

namespace Fetches.Fetch.Utils.IdGenerator
{
    public class IdService : IIdService
    {
        /// <summary>
        /// 备注：C#中MachineId为-1的情况下IdConverter转换有问题，暂未去详细了解
        /// </summary>
        protected long MachineId = 0;
        protected long GenMethod = 0;
        protected long Version = 0;

        protected IdType IdType;
        protected IdMeta IdMeta;

        protected IdConverter IdConverter;
        protected IdTimer timer;
        private LockIdPopulator populator = new LockIdPopulator();

        public IdService()
        {
            IdType = IdType.Seconds;
            Init();
        }

        public IdService(IdType idType)
        {
            IdType = idType;
            Init();
        }

        private void Init()
        {
            if (IdMeta == null)
            {
                IdMeta = IdMeta.GetIdMeta(IdType);
            }
            if (IdConverter == null)
            {
                IdConverter = new IdConverter();
            }
            if (timer == null)
            {
                timer = new IdTimer();
            }
            timer.Init(IdMeta, IdType);

            var envMachineId = Environment.GetEnvironmentVariable("MachineId");
            if (!string.IsNullOrEmpty(envMachineId))
            {
                MachineId = Convert.ToInt32(envMachineId);
            }
        }

        public long GenerateId()
        {
            var id = new Id
            {
                Machine = MachineId,
                GenMethod = GenMethod,
                Type = (long)IdType,
                Version = Version
            };

            populator.populateId(timer, id, IdMeta);

            return IdConverter.Convert(id, IdMeta);
        }

        public Id ExplanId(long id)
        {
            return IdConverter.Convert(id, IdMeta);
        }

        /// <summary>
        /// 注意，这里传入的是UTC时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public long TransTime(DateTime time)
        {
            return timer.GenTime(time);
        }

        public DateTime TransTime(long time)
        {
            return timer.TransTime(time);
        }

        public long MakeId(long time, long seq)
        {
            return MakeId(time, seq, MachineId);
        }

        public long MakeId(long time, long seq, long machine)
        {
            return MakeId(GenMethod, time, seq, machine);
        }

        public long MakeId(long genMethod, long time, long seq, long machine)
        {
            return MakeId((long)IdType, genMethod, time, seq, machine);
        }

        public long MakeId(long type, long genMethod, long time, long seq, long machine)
        {
            return MakeId(Version, type, genMethod, time, seq, machine);
        }

        public long MakeId(long version, long type, long genMethod, long time, long seq, long machine)
        {
            var id = new Id(machine, seq, time, genMethod, type, version);
            return IdConverter.Convert(id, IdMeta);
        }
    }
}
